#include "stdafx.h"
#include <xwt/xwt_graphics.h>

// Font class...
bool xwt::Font::Create (const sys_tchar *face_name, int size, HDC hRefDC, long weight) {
	Delete ();

	LOGFONT logfont;
	memset (&logfont, 0, sizeof(logfont));
	logfont.lfCharSet = DEFAULT_CHARSET;
	logfont.lfHeight = size;
	logfont.lfWeight = weight;
	lstrcpyn (logfont.lfFaceName, face_name, sizeof(logfont.lfFaceName) - 1);

	HDC hdc = hRefDC == NULL ? ::GetDC (NULL) : hRefDC;
	if (!hdc) return FALSE;
	
	// lfHeight must be scaled based on passed DC units
	POINT pt, ptOrg = {0, 0};
	pt.y = ::GetDeviceCaps (hdc, LOGPIXELSY) * logfont.lfHeight;
	pt.y/= 72;    // 72 points/inch, 10 decipoints/point
	::DPtoLP (hdc, &pt, 1);
	::DPtoLP (hdc, &ptOrg, 1);
	logfont.lfHeight = -abs(pt.y - ptOrg.y);

	if (hRefDC == NULL) ::ReleaseDC (NULL, hdc);

	// create the point font
	m_hFont = ::CreateFontIndirect (&logfont);
	return m_hFont != NULL;
}

// GC class.

void xwt::GC::Dispose () {
#ifdef WIN32
	if (m_hdc) {
		// restore HDC context before we destroy it
		::RestoreDC (m_hdc, m_dc_context);

		if (m_hdc_type == hdcTypeWindow) {			
			// release the HDC handle if it is the window DC created
			// using GetDC or GetWindowDC
			::ReleaseDC (m_hWnd, m_hdc);
		} else if (m_hdc_type == hdcTypePaint) {
			// end WM_PAINT message
			::EndPaint (m_hWnd, &m_ps);			
		}
	}

	// reset the vars...
	m_hWnd = NULL;
	m_hdc = NULL;
	m_hdc_type = hdcTypeInvalid;
	m_flag_erase_bkgnd = false;
#endif
}

xwt::GC::GC () {
#ifdef WIN32
	m_hWnd = NULL;
	m_hdc = NULL;
	m_hdc_type = hdcTypeInvalid;
#endif
	m_flag_erase_bkgnd = false;
}

void xwt::GC::SetFillColor (const Color &color) {
	HBRUSH hBrush = ::CreateSolidBrush ( ToWin32Color(color) );
	::SelectObject (m_hdc, hBrush);
}

void xwt::GC::SetPenColor (const Color &color) {
	HPEN hPen = ::CreatePen (PS_SOLID, 1, ToWin32Color(color) );
	::SelectObject (m_hdc, hPen);
};

void xwt::GC::Rectangle (int x, int y, int cx, int cy) {
	::Rectangle (m_hdc, x, y, x + cx - 1, y + cy - 1);
}

// static factory methods...
#ifdef WIN32
xwt::GC *xwt::GC::CreateWindowGC (HWND hwnd) {
	GC *gc = new GC ();
	gc->m_hWnd = hwnd;
	gc->m_hdc = ::GetDC (gc->m_hWnd);
	gc->m_hdc_type = hdcTypeWindow;
	gc->m_dc_context = ::SaveDC (gc->m_hdc);

	return gc;
}

xwt::GC *xwt::GC::CreatePaintGC (HWND hWnd) {
	GC *gc = new GC ();
	gc->m_hWnd = hWnd;
	gc->m_hdc = ::BeginPaint (hWnd, &gc->m_ps);	
	gc->m_hdc_type = hdcTypePaint;
	gc->m_flag_erase_bkgnd = gc->m_ps.fErase ? true : false;
	gc->m_dc_context = ::SaveDC (gc->m_hdc);

	return gc;
}

#endif /* WIN32 */

// MemoryBitmap class...

bool xwt::MemoryBitmap::Create (int cx, int cy, HDC hRefDC)
{
	Dispose ();

	if ( !(m_hDC = ::CreateCompatibleDC (hRefDC)) ) {
		return true;
	}

	// load the imagesheet bitmap from the app resource
	if ( !(m_hBitmap = ::CreateCompatibleBitmap (hRefDC, cx, cy)) ) {
		::DeleteDC (m_hDC);
		m_hDC = NULL;
		return false;
	}

	// save current bitmap and select the image sheet bitmap into the DC
	m_hOldBitmap = ::SelectObject (m_hDC, (HGDIOBJ) m_hBitmap);

	return true;
}

void xwt::MemoryBitmap::Dispose ()
{
	if (m_hDC != NULL)
	{
		::SelectObject (m_hDC, m_hOldBitmap);
		::DeleteObject ((HGDIOBJ)m_hBitmap);

		m_hBitmap = NULL;
		m_hOldBitmap = NULL;

		DeleteDC (m_hDC);
		m_hDC = NULL;
	}
}
